/*  File Name	: Table.cpp
 *  Author		: Javie Pong
 *	 E-mail		: 823960168@qq.com
 *  Created on	: 2012-8-5
 *  Description:
 */

#include "Table.h"
#include "ProcResult.h"
#include "Cmd.h"
#include "EngineMonitor.h"
#include <algorithm>
#include "EnginePlayer.h"
#include "ComDefine.h"
#include <math.h>

#define PLAYER_PER_TABLE 8 //每张桌子的玩家数量
#define DEAL_TIME_PER_CARD 0.6 //客户端发一张牌用的时间

#ifdef DEBUG
#define WAIT_TIME 15
#else
#define WAIT_TIME 15
#endif

Table::Table(int p)
{
	this->base_info_.reset();
	this->monitor_ = NULL;

	reset();
}

Table::~Table()
{
}

int Table::init(EngineMonitor *monitor)
{
	if(NULL==monitor || NULL==monitor->timer_reactor() )
	{
		return -1;
	}
	this->monitor_ = monitor;
	this->reactor(this->monitor_->timer_reactor());
	this->poker_.init(this);
	return 0;
}

void Table::reset(void)
{
	this->game_step_ 	= NONE_STEP;
	this->total_chips_ 	=0;
	this->player_count_ = 0;
	this->player_in_game_ = 0;
	this->player_gaming_ =0;
	this->is_start_ 	= false;
	this->is_reset_dealer_ 	= true;
	this->is_wait_ 		= true;
	this->is_calculating_ = false;
	this->prepare_wait_ = false;
	this->last_oper_player_ = -1;

	this->timer_name_.clear();
	this->player_vec_.clear();
	this->left_pos_.clear();
	this->all_in_chips_vec_.clear();
	this->chips_record_vec_.clear();

	for (int i = 0; i < PLAYER_PER_TABLE; i++)
	{
		this->player_vec_.push_back(NULL);
		this->left_pos_.push_back(i);
		this->chips_record_vec_.push_back(0);
	}
	std::random_shuffle(this->left_pos_.begin(),this->left_pos_.end());
}

EngineMonitor *Table::monitor(void)
{
	return this->monitor_;
}

const TableBaseInfo &Table::base_info(void)
{
	return this->base_info_;
}

void Table::set_base_info(const TableBaseInfo &info)
{
	this->base_info_ = info;
	this->timer_name_.clear();
	char name[50]={0};
	sprintf(name,"table:%d",this->base_info_.table_id);
	this->timer_name_ = name;
}

int Table::table_id(int id)
{
	if (id != 0)
	{
		this->base_info_.table_id = id;
	}
	return this->base_info_.table_id;
}

int Table::min_chips(void)
{
	return this->base_info_.min_chips_;
}

int Table::min_bet(void)
{
	return this->base_info_.min_bet;
}

int Table::start_timer(void)
{
	int interval = 5;
#ifdef DEBUG
	interval = rand()%15;
#endif
	return this->schedule_timer(TimeValue(1),TimeValue(interval));
}

int Table::stop_timer(void)
{
	return this->cancel_timer();
}

bool Table::is_full(void)
{
	return (this->player_count_ >= PLAYER_PER_TABLE);
}

bool Table::is_start(void)
{
	return this->is_start_;
}

int Table::player_count(void)
{
	LockGuardReturn(RT_MUTEX, lock, this->rt_mutex_, -1);
	return this->player_count_;
}

int Table::make_up_table_info(MessageBlock *mb, int start_index,bool with_card)
{
	if (NULL == mb)
	{
		return -1;
	}
	*mb << this->table_id() << this->is_start_;
	if(with_card && this->is_start_)
	{
		*mb << 5;
		for(int i=0;i<5;i++)
		{
			int type =0,num = 0;
			if(NULL!=this->pub_card_[i])
			{
				type =this->pub_card_[i]->type_ ;
				num = this->pub_card_[i]->number_;
			}
			*mb << type << num;
		}
	}

	*mb	<< (int)this->player_vec_.size();

	EnginePlayer *player = NULL;
	int i = start_index;
	int hide = (this->game_step_==GAME_END)?1:0;
	for (int j = 0; j < PLAYER_PER_TABLE; j++) //类似循环队列读取
	{
		if (i >= PLAYER_PER_TABLE)
		{
			i = 0;
		}
		player = this->player_vec_[i];
		if (NULL != player)
		{
			*mb << (i + 1) << player->role_id()
					<< player->account()
					<< (int)player->game_status_
					<< player->chips_in_table_
					<< player->cur_bet_chips_;
			if(with_card && (player->is_in_game() ))//|| player->is_fold()))
			{
				*mb << hide << (int)player->card_[0]->type_ << player->card_[0]->number_
							<< (int)player->card_[1]->type_ << player->card_[1]->number_;
			}
		}
		else
		{
			*mb << (i+1) << 0;
		}
		if ((i + 1) % PLAYER_PER_TABLE == start_index)
		{
			break;
		}
		i++;
	}
	return 0;
}

int Table::make_up_private_card_info(MessageBlock *mb)
{
	*mb << this->table_id() << (int)this->player_vec_.size();

	EnginePlayer *player = NULL;
	//int i = 0;
	//int hide = (this->game_step_==GAME_END)?1:0;
	for (int i = 0; i < PLAYER_PER_TABLE; i++) //类似循环队列读取
	{
		player = this->player_vec_[i];
		if (NULL != player && player->is_in_game())
		{
			*mb << (i + 1) << player->role_id()
					<< (int) player->card_[0]->type_
					<< player->card_[0]->number_
					<< (int) player->card_[1]->type_
					<< player->card_[1]->number_;
		}
		else
		{
			*mb << (i + 1) << 0;
		}
	}
	return 0;
}

int Table::player_enter(EnginePlayer *player, int pos)
{
	LockGuardReturn(RT_MUTEX, lock, this->rt_mutex_, -1);
	pos -= 1;
	//LOG((DEBUG_LOG,"Table::enter_table-->[table:%d][seat:%d]",this->table_id(),pos));
	if (pos < 0 || pos >= (int) this->player_vec_.size()
			|| NULL != this->player_vec_[pos])
	{
		return ERROR_CLIENT_INFO;
	}
	this->player_vec_[pos] = player;
	this->player_count_++;
	this->is_reset_dealer_ = true;
	return 0;
}

int Table::player_exit(EnginePlayer *player)
{
	LockGuardReturn(RT_MUTEX, lock, this->rt_mutex_, -1);
	if (this->player_vec_[player->table_index()] != NULL)
	{
		this->player_vec_[player->table_index()] = NULL;
		this->player_count_--;
		if(player->is_gaming())
		{
			this->player_in_game_--;
			this->player_gaming_ --;
		}
		this->left_pos_.push_back(player->table_index());
		std::random_shuffle(this->left_pos_.begin(), this->left_pos_.end());
		if (player->game_status_ > GAME_STATUS_PREPARE)
		{
			this->is_reset_dealer_ = true;
		}
		return 0;
	}
	return -1;
}

bool Table::check_start_condition(void)
{
	if (this->player_count_ >=2)
	{
		return true;
	}
	return false;
}

bool Table::check_curr_player(void)
{
	if (this->cur_oper_player_ == -1)
	{
		this->cur_oper_player_ = this->next_player_index(this->cur_oper_player_);
		if (this->cur_oper_player_ == -1)
		{
			return false;
		}
	}
	return true;
}

int Table::handle_timeout(void)
{
	if(this->is_calculating_)
	{
		return 0;
	}
	LockGuardReturn(RT_MUTEX, lock, this->rt_mutex_, 0);
	if(!this->is_start_ && this->player_count_ <2)
	{
		return 0;
	}
	LOG((INFO_LOG,"Table::handle_timeout-->[%s][%d][count:%d]",
			this->name().c_str(),this->is_start_,this->player_count_));
	return this->start_game();
}

int Table::start_game(void)
{
	if (!this->is_start_)
	{
		return this->prepare();
	}
	else
	{
		switch (this->game_step_)
		{
			case FISRT_DEAL: //第一次发牌
			{
				return this->holecards();
			}
			case FISRT_BET: //第一次下盲注
			{
				return this->pre_flop();
			}
			case SECOND_DEAL: //发3张底牌
			{
				return this->flop();
			}
			case SECOND_BET: //第二次下注
			{
				return this->flop_round();
			}
			case DEAL_TURN: //发转牌
			{
				return this->turn();
			}
			case THIRD_BET: //第3次下注
			{
				return this->turn_round();
			}
			case DEAL_RIVER: ////发河牌
			{
				return this->river();
			}
			case FOURTH_BET: //第4次下注
			{
				return this->river_round();
			}
			case GAME_END: //计算结果
			{
				return this->end_game();
			}
			case CLEAN_DATA:
			{
				this->clear();
				return 0;
			}
			default:
			{
				LOG((ERROR_LOG,"Table::start_game-->unknown [step:%d][table:%d]",
						this->game_step_,this->table_id()));
				break;
			}
		}
	}
	return 0;
}

int Table::prepare(void)
{
	LOG((INFO_LOG,"Table::prepare-->[timer:%l][table:%d][is_wait:%d]",
			this->timer_id(),this->table_id(),this->is_wait_));
	if (this->is_wait_)
	{
		this->is_wait_ = false;
		bool wait = false;

		EnginePlayer *player = NULL;
		for (int i=0;i<PLAYER_PER_TABLE; i++)
		{
			player = this->player_vec_[i];
			if(NULL!=player && !player->is_ready())
			{
				wait = true;
				player->notify_operation(0);
			}
		}
		int time = 3;
		if (wait)
		{
			time = WAIT_TIME;
		}
		this->notify_time_ = TimeValue::now_time_in_sec()+time;
		return this->refresh_timer(TimeValue(time));
	}
	else
	{
		//判断是否够人数进行游戏
		int count = 0;
		EnginePlayer *player = NULL;
		for (int i=0; i<PLAYER_PER_TABLE; i++)
		{
			player = this->player_vec_[i];
			if (player!=NULL&& player->is_ready() && player->chips_in_table_ > this->base_info_.cost)
			{
				count++;
			}
		}
		if (count<2)
		{
			this->prepare_wait_=false;
			this->is_wait_ = true;
			int time = 5;
			this->notify_time_ = TimeValue::now_time_in_sec()+time;
			return this->refresh_timer(TimeValue(time));
		}
		if(this->prepare_wait_==false)
		{
			this->prepare_wait_=true;
			return this->refresh_timer(TimeValue(5));
		}

		//设置本轮参与的游戏玩家并扣除费用
		this->is_start_ = true;
		this->player_in_game_ = count;
		this->player_gaming_ = count;
		for (int i=0; i<PLAYER_PER_TABLE; i++)
		{
			player = this->player_vec_[i];
			if(NULL!=player && player->is_ready()&& player->chips_in_table_>this->base_info_.cost)
			{
				player->sub_cost(RECORD_FEE,this->base_info_.cost);
				player->notify_update_info(UPDATE_CHIPS);
				player->set_game_status(GAME_STATUS_START);
				player->notify_update_info(UPDATE_GAME_STATUS);
			}
		}
		this->game_step_ = FISRT_DEAL;
		this->refresh_timer(TimeValue(1));
	}
	return 0;
}

//底牌
int Table::holecards(void)
{
	LOG((INFO_LOG,"Table::holecards-->[timer:%l][table:%d]",this->timer_id(),this->table_id()));

	this->to_shuffle();
	if(this->dealer()!=0)
	{
		LOG((ERROR_LOG,"Table::holecards-->dealer error"));
		this->clear();
		return this->refresh_timer(TimeValue(WAIT_TIME));
	}
	this->to_deal();
	this->game_step_ = FISRT_BET;
	this->cur_oper_player_ = this->next_player_index(this->large_player_);

	int wait_time = this->player_in_game_*2*DEAL_TIME_PER_CARD*1000;
	return this->refresh_timer(TimeValue(0,wait_time));
}

//底牌权
int Table::pre_flop(void)
{
	return this->run_round(SECOND_DEAL);
}

//翻牌 - 首三张公共牌
int Table::flop(void)
{
	LOG((INFO_LOG,"Table::flop-->[timer:%l][table:%d]",this->timer_id(),this->table_id()));

	this->to_cut();
	MessageBlock mb(2048);
	mb << this->table_id() << 3;
	for(int i=0;i<3;i++)
	{
		mb << (int)this->poker_.card_vec()[poker_index_]->type_
			<< (int)this->poker_.card_vec()[poker_index_]->number_;
		this->pub_card_[i] = this->poker_.card_vec()[poker_index_];
		poker_index_++;

		LOG((INFO_LOG,"Table::flop[timer:%l][table:%d][card:%s]\n",this->timer_id(),
				this->table_id(),this->pub_card_[i]->name_.c_str()));
	}
	this->broadcast_to_table(STC_DEAL_PUBLIC,&mb);
	this->game_step_ = SECOND_BET;
	this->cur_oper_player_ = this->next_player_index(this->small_player_);

	int wait_time = 3*DEAL_TIME_PER_CARD*1000;
	return this->refresh_timer(TimeValue(0,wait_time));
}

//翻牌圈
int Table::flop_round(void)
{
	return this->run_round(DEAL_TURN);
}

//转牌 - 第四张公共牌
int Table::turn(void)
{
	LOG((INFO_LOG,"Table::turn-->[timer:%l][table:%d]",this->timer_id(),this->table_id()));

	this->to_cut();
	MessageBlock mb(2048);
	mb << this->table_id();
	mb << (int) this->poker_.card_vec()[poker_index_]->type_
				<< (int) this->poker_.card_vec()[poker_index_]->number_;
	this->pub_card_[3] = this->poker_.card_vec()[poker_index_];
	poker_index_++;

	LOG((INFO_LOG,"Table::turn[table:%d][card:%s]\n",this->table_id(),this->pub_card_[3]->name_.c_str()));

	this->broadcast_to_table(STC_DEAL_TURN, &mb);
	this->game_step_ = THIRD_BET;
	this->cur_oper_player_ = this->next_player_index(this->small_player_);

	int wait_time = ceil(DEAL_TIME_PER_CARD);
	return this->refresh_timer(TimeValue(wait_time));
}

//转牌圈
int Table::turn_round(void)
{
	return this->run_round(DEAL_RIVER);
}

int Table::river(void)
{
	this->to_cut();
	MessageBlock mb(2048);
	mb << this->table_id();
	mb << (int) this->poker_.card_vec()[poker_index_]->type_
				<< (int) this->poker_.card_vec()[poker_index_]->number_;
	this->pub_card_[4] = this->poker_.card_vec()[poker_index_];
	poker_index_++;

	LOG((INFO_LOG,"Table::river[timer:%l][table:%d][card:%s]\n",
			this->timer_id(),this->table_id(),this->pub_card_[4]->name_.c_str()));

	this->broadcast_to_table(STC_DEAL_RIVER, &mb);
	this->game_step_ = FOURTH_BET;
	this->cur_oper_player_ = this->next_player_index(this->small_player_);

	int wait_time = ceil(DEAL_TIME_PER_CARD);
	return this->refresh_timer(TimeValue(wait_time));
}

// 河牌圈
int Table::river_round(void)
{
	return this->run_round(GAME_END);
}

int Table::end_game(void)
{
	if(this->is_calculating_)
	{
		return 0;
	}

	this->refresh_timer(TimeValue(WAIT_TIME/2));
	this->is_calculating_ = true;

	LOG((INFO_LOG,"Table::end_game-->[timer:%l][table:%d]",this->timer_id(),this->table_id()));
	if(this->player_in_game_<=1)
	{
		int total_chips = 0;
		for (int i = 0; i < (int)chips_record_vec_.size(); i++)
		{
			total_chips += chips_record_vec_[i];
		}
		EnginePlayer *player = NULL;
		for (int i = 0; i < PLAYER_PER_TABLE; i++)
		{
			player = this->player_vec_[i];
			if(NULL!=player && player->is_in_game())
			{
				break;
			}
		}
		if (NULL != player && player->is_in_game())
		{
			player->win_chips_ = total_chips;
			if(total_chips-player->cur_bet_chips_>0)
			{
				MessageBlock mb(1024);
				mb << this->table_id() << player->role_id() << player->seat()
						<< UPDATE_WIN_CHIPS;
				mb << total_chips-player->cur_bet_chips_;
				this->broadcast_to_table(STC_BROADCAST_TABLE_INFO,&mb);
			}
			player->game_end();
		}
	}
	else
	{
		//摊牌
		MessageBlock mb(2048);
		this->make_up_private_card_info(&mb);
		this->broadcast_to_table(STC_DISPLAY_CARD, &mb);

		//获取结果
		EnginePlayer *player = NULL;
		for (int i = 0; i < PLAYER_PER_TABLE; i++)
		{
			player = this->player_vec_[i];
			if (NULL != player && player->is_in_game())
			{
				ProcResult result;
				if (result.make_result(player, player->card_, this->pub_card_)!= 0)
				{
					LOG((ERROR_LOG,"Table::end_game [account:%s][roleid:%d] error",
							player->account().c_str(),player->role_id()));
				}
				else
				{
					this->result_map_.insert(std::pair<int, ProcResult>(player->role_id(), result));
				}
			}
		}

		this->make_pool(GAME_END);
		this->broadcast_result();

		for (int i = 0; i < PLAYER_PER_TABLE; i++)
		{
			player = this->player_vec_[i];
			if (NULL != player && player->is_in_game())
			{
				player->game_end();
			}
		}
	}
	this->is_calculating_ = false;
	this->game_step_ = CLEAN_DATA;
	return this->refresh_timer(TimeValue(WAIT_TIME/2));
}

void Table::clear(void)
{
	LOG((INFO_LOG,"Table::clear-->[timer:%l][table:%d]",this->timer_id(),this->table_id()));

	EnginePlayer *player = NULL;
	for(int i=0;i<PLAYER_PER_TABLE;i++)
	{
		player = this->player_vec_[i];
		if(NULL!=player)
		{
			if(player->game_status_> GAME_STATUS_PREPARE)
			{
				player->set_game_status(GAME_STATUS_STOP);
			}
			player->game_step_ = NONE_STEP;
			player->notify_update_info(UPDATE_CLEAN);
		}
	}

	this->is_calculating_ = false;
	this->prepare_wait_ = false;
	this->is_wait_ = true;
	this->is_start_ = false;
	this->game_step_ = NONE_STEP;
	this->small_player_ = 0;
	this->large_player_ = 0;
	this->cur_oper_player_ = 0;
	this->last_oper_player_ = -1;
	this->poker_index_ = 0;
	this->cur_max_bet_ = 0;
	this->total_chips_ = 0;
	this->player_in_game_ = 0;
	this->player_gaming_ =0;

	this->result_map_.clear();
	this->all_in_chips_vec_.clear();

	for (int i = 0; i <(int)chips_record_vec_.size(); i++)
	{
		this->chips_record_vec_[i]=0;
	}

	this->chips_pool_.clear();
	for(int i=0;i<5;i++)
	{
		this->pub_card_[i] = NULL;
	}
	this->refresh_timer(TimeValue(1));
}

//确定庄家和大小盲点
int Table::dealer(void)
{
	int index = 0;
	if (this->is_reset_dealer_)//有人进入或离开，则重新确定庄家
	{
		index = rand() % PLAYER_PER_TABLE;
	}
	else
	{
		if(last_dealer_!=(PLAYER_PER_TABLE-1))
		{
			index = last_dealer_ + 1;
		}
	}
	this->is_reset_dealer_ = false;

	this->last_dealer_ = -1;
	this->small_player_ = -1;
	this->large_player_ = -1;

	int min_bet = this->base_info_.min_bet;
	EnginePlayer *player = NULL;
	int i = index;
	for (int j = 0; j < PLAYER_PER_TABLE; j++)
	{
		if (i >= PLAYER_PER_TABLE)
		{
			i = 0;
		}
		player = this->player_vec_[i];
		if (NULL != player && player->is_gaming())
		{
			if(this->last_dealer_==-1)
			{
				this->last_dealer_ = i;
			}
			else if(this->small_player_==-1)
			{
				this->small_player_ = i;
				player->cur_bet_chips_ = min_bet;
				this->chips_record_vec_[i]=player->cur_bet_chips_;
				player->chips_in_table_ -=min_bet;
				player->notify_update_info(UPDATE_CHIPS);
				player->game_step_ = FISRT_BET;
				this->cur_max_bet_ =min_bet;
			}
			else if(this->large_player_==-1)
			{
				this->large_player_ = i;
				player->cur_bet_chips_ = min_bet*2;
				this->chips_record_vec_[i]=player->cur_bet_chips_;
				player->chips_in_table_ -= min_bet*2;
				this->cur_max_bet_ = min_bet*2;
				player->game_step_ = FISRT_BET;
				player->notify_update_info(UPDATE_CHIPS);
			}
			else
			{
				break;
			}
		}
		if ((i + 1) % PLAYER_PER_TABLE == index)
		{
			break;
		}
		i++;
	}
	if(this->last_dealer_==-1 || this->small_player_==-1)
	{
		return -1;
	}

	MessageBlock mb(2048);
	mb << this->table_id() << 3;
	mb << (this->last_dealer_+1) << 0 ;
	mb << (this->small_player_+1) << this->player_vec_[this->small_player_]->cur_bet_chips_;
	if(this->large_player_!=-1)
	{
		this->last_oper_player_ =this->large_player_;
		mb << (this->large_player_+1) << this->player_vec_[this->large_player_]->cur_bet_chips_;
	}
	else
	{
		mb << 0;
		//this->large_player_=this->small_player_;
		this->last_oper_player_ = this->small_player_;
	}
	LOG((INFO_LOG,"Table::dealer-->[%d][%d][%d]",this->last_dealer_,this->small_deal_,this->large_player_));
	return this->broadcast_to_table(STC_DEALER_INFO,&mb);
}

int Table::next_player_index(int cur_index)
{
	if(cur_index==-1)
	{
		cur_index = this->last_oper_player_;
	}
	EnginePlayer *player = NULL;
	int start_index = cur_index+1;
	for (int i = 0; i < PLAYER_PER_TABLE; i++)
	{
		if (start_index >= PLAYER_PER_TABLE)
		{
			start_index = 0;
		}
		player = this->player_vec_[start_index];
		if (NULL != player && player->is_gaming())
		{
			this->last_oper_player_ = start_index;
			return start_index;
		}
		if ((start_index + 1) % PLAYER_PER_TABLE == cur_index)
		{
			break;
		}
		start_index++;
	}
	return -1;
}

bool Table::is_calculating(void)
{
	return this->is_calculating_;
}

bool Table::is_fold(EnginePlayer *player)
{
	if(!player->is_all_in() && (player->cur_bet_chips_<this->cur_max_bet_
			||(player->cur_bet_chips_==this->cur_max_bet_&& player->game_step_<this->game_step_)))
	{
		player->fold(NULL,true);
		return true;
	}
	return false;
}

bool Table::is_bet_end(int cur_index)
{
	EnginePlayer *player = NULL;
	for (int i = 0; i < PLAYER_PER_TABLE; i++)
	{
		player = this->player_vec_[i];
		if(NULL!=player &&player->is_gaming())//&&!player->is_fold() && !player->is_all_in())
		{
			 if(player->cur_bet_chips_< this->cur_max_bet_
					 || player->game_step_ < this->game_step_)
			 {
				 return false;
			 }
		}
	}
	return true;
}

int Table::make_pool(GameStep step)
{
	EnginePlayer *player = NULL;
	IntVector &chips_vec =this->all_in_chips_vec_;
	this->chips_pool_.clear();
	this->total_chips_ = 0;

	if (chips_vec.size()>0)
	{
		std::sort(chips_vec.begin(), chips_vec.end(),Table::cmp_chips);
		for (int j = 0; j < (int)chips_vec.size(); j++)
		{
			int cur_all_in = chips_vec[j];//当前all in 值
			int all_in_level =(j > 0) ?(cur_all_in - chips_vec[j-1]) : cur_all_in;//all in 等级差

			ChipsPool pool;
			for (int i = 0; i < PLAYER_PER_TABLE; i++)
			{
				int chips = this->chips_record_vec_[i];
				bool count_in = (j>0)?(chips>chips_vec[j-1]):(chips>0);
				if (count_in)
				{
					int player_chips = all_in_level;
					if (chips <= cur_all_in)
					{
						player_chips =(j <= 0) ?(chips):(chips- chips_vec[j-1]);
					}
					player = this->player_vec_[i];
					if(player!=NULL && player->is_in_game())
					{
						pool.player_vec_.push_back(player);
					}
					pool.total_chips += player_chips;
				}
			}
			if (pool.total_chips <= 0)
			{
				continue;
			}
			this->total_chips_ += pool.total_chips;
			this->chips_pool_.push_back(pool);
		}
	}
	{//当没有边池时，形成主池；或有边池时形成最后一个边池
		int total_chips = 0;
		ChipsPool pool;
		int chips_size=chips_vec.size();
		for (int i = 0; i < PLAYER_PER_TABLE; i++)
		{
			player = this->player_vec_[i];
			if (player==NULL ||(chips_size>0 && chips_record_vec_[i]<= chips_vec[chips_size- 1]))
			{
				continue;
			}
			total_chips += chips_size>0?(chips_record_vec_[i]- chips_vec[chips_size-1]):chips_record_vec_[i];
			if (player->is_in_game())
			{
				pool.player_vec_.push_back(player);
			}
		}
		if(total_chips>0)
		{
			pool.total_chips = total_chips;
			this->total_chips_ += pool.total_chips;
			this->chips_pool_.push_back(pool);
		}
	}
	return this->notify_pool_info(step);
}

int Table::notify_pool_info(GameStep step)
{
	bool is_game_end = false;
	if(step==GAME_END)
	{
		is_game_end = true;
	}

	MessageBlock mb(1024);
	mb << this->table_id() << this->total_chips_ << is_game_end;
	mb << (int)this->chips_pool_.size();
	for(int i=0;i<(int)this->chips_pool_.size();i++)
	{
		mb << (i+1)<< this->chips_pool_[i].total_chips;
	}
	return this->broadcast_to_table(STC_POOL_INFO,&mb);
}

//洗牌
void Table::to_shuffle(void)
{
	int times = rand()%3+1;
	for(int i=0;i < times;i++)
	{
		this->poker_.shuffle_poker();
	}
}

//发牌
int Table::to_deal(void)
{
	EnginePlayer *player = NULL;
	MessageBlock mb(sizeof(int)*20);
	int start_index = this->small_player_;
	for (int i = 0; i < PLAYER_PER_TABLE; i++)
	{
		if (start_index >= PLAYER_PER_TABLE)
		{
			start_index = 0;
		}
		player = this->player_vec_[start_index];
		if (NULL != player )//&& player->is_gaming())
		{
			mb.reset();
			player->card_[0] = this->poker_.card_vec()[poker_index_++];
			player->card_[1] = this->poker_.card_vec()[poker_index_++];
			LOG((INFO_LOG,"Table::to_deal[%d][%s][%s]\n",player->role_id(),
					player->card_[0]->name_.c_str(),player->card_[1]->name_.c_str()));
			mb << this->table_id() << player->seat() << 2
					<< player->card_[0]->type_<< player->card_[0]->number_
					<< player->card_[1]->type_<< player->card_[1]->number_;
			player->respond_success_to_client(STC_DEAL_PRIVATE,&mb);
		}
		if ((start_index + 1) % PLAYER_PER_TABLE == this->small_player_)
		{
			break;
		}
		start_index++;
	}
	return 0;
}

//切牌
int Table::to_cut(void)
{
	Card *card = this->poker_.card_vec()[this->poker_index_];
	if(NULL==card)
	{
		return 0;
	}
	this->poker_index_++;
	LOG((INFO_LOG,"Table::to_cut[%d][%s]\n",this->table_id(),card->name_.c_str()));
	MessageBlock mb(sizeof(int)*10);
	mb << card->type_ << card->number_;
	return this->broadcast_to_table(STC_CUT_POKER,&mb);
}

int Table::run_round(GameStep next_step)
{
	if(this->check_curr_player()==false)
	{
		this->game_step_ = next_step;
		return this->refresh_timer(TimeValue(1));
	}

	EnginePlayer *player = this->player_vec_[this->cur_oper_player_];
	if(NULL==player)
	{
		LOG((ERROR_LOG,"Table::run_round-->[%d][timer:%l][table:%d] player is NULL",
				this->game_step_,this->timer_id(),this->table_id()));
		return 0;
	}

	if(this->player_in_game_<=1)
	{
		this->game_step_ = next_step;
		return this->refresh_timer(TimeValue(1));
	}

	if(player->is_wait_)
	{
		if (this->player_gaming_ <= 1 && player->cur_bet_chips_>=this->cur_max_bet_)
		{
			this->game_step_ = next_step;
			return this->refresh_timer(TimeValue(1));
		}

		LOG((INFO_LOG,"Table::run_round-->[%d][timer:%l][table:%d][account:%s]",
				this->game_step_,this->timer_id(),this->table_id(),player->account().c_str()));
		player->is_wait_ = false;
		player->notify_operation(this->cur_max_bet_);
		this->notify_operator(player,WAIT_TIME);
		return this->refresh_timer(TimeValue(WAIT_TIME, 0));
	}
	else
	{
		player->is_wait_ = true;

		if(!player->is_fold())
		{
			this->is_fold(player);
		}

		if(this->is_bet_end())
		{
			this->make_pool(this->game_step_);
			this->game_step_ = next_step;
			return this->refresh_timer(TimeValue(1));
		}
		this->cur_oper_player_ = this->next_player_index(this->cur_oper_player_);
		return this->refresh_timer(TimeValue(1));
	}
	return 0;
}

int Table::player_start(EnginePlayer *player)
{
	LockGuardReturn(RT_MUTEX, lock, this->rt_mutex_, -1);
	if(!this->prepare_wait_)
	{
		this->refresh_timer(TimeValue(0,500));//this->wait_time(),0));
	}
	return 0;
}

//下注
int Table::bet(EnginePlayer *player)
{
	player->game_step_ = this->game_step_;
	this->update_max_bet(player->cur_bet_chips_);
	this->update_chips_record(player->table_index(),player->cur_bet_chips_);
	return this->refresh_timer(TimeValue(1));
}

//加赌注
int Table::raise(EnginePlayer *player)
{
	player->game_step_ = this->game_step_;
	this->update_max_bet(player->cur_bet_chips_);
	this->update_chips_record(player->table_index(),player->cur_bet_chips_);
	return this->refresh_timer(TimeValue(1));
}

//全下
int Table::all_in(EnginePlayer *player)
{
	player->game_step_ = this->game_step_;
	this->update_max_bet(player->cur_bet_chips_);
	this->update_chips_record(player->table_index(),player->cur_bet_chips_);
	bool exsit = false;

	LockGuardReturn(RT_MUTEX,lock,this->rt_mutex_,-1);
	for(IntVector::iterator iter=this->all_in_chips_vec_.begin();
			iter!=this->all_in_chips_vec_.end();iter++)
	{
		if(*iter==player->cur_bet_chips_)
		{
			exsit = true;
			break;
		}
	}
	if(!exsit)
	{
		this->all_in_chips_vec_.push_back(player->cur_bet_chips_);
	}
	this->player_gaming_ --;
	return this->refresh_timer(TimeValue(1));
}

//弃牌
int Table::fold(EnginePlayer *player,bool force)
{
	if(!force)
	{
		LockGuardReturn(RT_MUTEX, lock, this->rt_mutex_, -1);
		this->player_in_game_--;
		this->player_gaming_ --;
		//this->refresh_timer(TimeValue(1));
	}
	else
	{
		this->player_in_game_--;
		this->player_gaming_ --;
		//this->refresh_timer(TimeValue(1));
	}
	this->refresh_timer(TimeValue(1));
	return 0;
}

//跟牌
int Table::call(EnginePlayer *player)
{
	player->game_step_ = this->game_step_;
	this->update_chips_record(player->table_index(),player->cur_bet_chips_);
	return this->refresh_timer(TimeValue(1));
}

//过牌
int Table::check(EnginePlayer *player)
{
	player->game_step_ = this->game_step_;
	return this->refresh_timer(TimeValue(1));
}

int Table::cmp_result(ProcResult r1, ProcResult r2)
{
	if (r1.type() == r2.type())
	{
		switch(r1.type())
		{
			case ROYAL_FLUSH://皇家同花顺
			case STRAIGHT_FLUSH://同花顺
			case STRAIGHT://顺子
			{
				return (r1.result()[0]->number_ > r2.result()[0]->number_);
			}
			case FOUR_OF_A_KIND://四条
			case SUIT://同花
			case FULL_HOUSE://葫芦
			case THREE_OF_A_KIND://三条
			case TWO_PAIRS://两对
			case ONE_PAIR://一对
			case HIGH_CARD://高牌
			{
				for (int i = 0; i < (int) r1.result().size(); i++)
				{
					if (r1.result()[i]->number_ != r2.result()[i]->number_)
					{
						return (r1.result()[i]->number_ > r2.result()[i]->number_);
					}
				}
				return false;
			}
			default:
			{
				return false;
			}
		}
	}
	return r1.type() > r2.type();
}

bool Table::is_equal(ProcResult &r1, ProcResult &r2)
{
	if (r1.type()==r2.type())
	{
		for (int i = 0; i < (int) r1.result().size(); i++)
		{
			if (r1.result()[i]->number_ != r2.result()[i]->number_)
			{
				return false;
			}
		}
		return true;
	}
	return false;
}

int Table::cmp_chips(const int &v1,const int &v2)
{
	return v1 <v2;
}

int Table::assign_pos(void)
{
	if(this->left_pos_.size()<=0)
	{
		return -1;
	}
	int pos = this->left_pos_[0];
	std::vector<int>::iterator iter= this->left_pos_.begin();
	this->left_pos_.erase(iter);
	return pos;
}

void Table::update_max_bet(int value)
{
	if(value>this->cur_max_bet_)
	{
		this->cur_max_bet_ = value;
	}
}

int Table::wait_time(void)
{
	int wait = this->notify_time_-TimeValue::now_time_in_sec();
	return (wait > 0 ? wait : 1);
}

int Table::update_chips_record(int index,int value)
{
	LockGuardReturn(RT_MUTEX,lock,this->rt_mutex_,-1);
	if(index<0 || index>=(int)chips_record_vec_.size())
	{
		return -1;
	}
	this->chips_record_vec_[index]=value;
	return 0;
}

int Table::cur_max_bet(void)
{
	return this->cur_max_bet_;
}

int Table::broadcast_to_table(int cmd,MessageBlock *mb,int self_id,bool to_self)
{
	EnginePlayer *player = NULL;
	for(int i=0;i<PLAYER_PER_TABLE;i++)
	{
		player = this->player_vec_[i];
		if(NULL==player || (!to_self && player->role_id()==self_id))
		{
			continue;
		}
		player->respond_success_to_client(cmd,mb);
	}
	return 0;
}

void Table::broadcast_result(void)
{
	for (int i = 0; i < (int) this->chips_pool_.size(); i++)
	{
		std::vector<ProcResult> result_vec;
		ChipsPool &pool = this->chips_pool_[i];
		for (int j = 0; j < (int) pool.player_vec_.size(); j++)
		{
			ResultMap::iterator iter = this->result_map_.find(
					pool.player_vec_[j]->role_id());
			if (iter != this->result_map_.end())
			{
				result_vec.push_back(iter->second);
			}
		}
		//比较大小
		std::sort(result_vec.begin(), result_vec.end(), Table::cmp_result);
		int reward_count = 1;
		for (int i = 0; i < (int) (result_vec.size() - 1); i++)
		{
			if (!Table::is_equal(result_vec[i], result_vec[i + 1]))
			{
				break;
			}
			reward_count++;
		}

		int chips = pool.total_chips / reward_count;
		EnginePlayer *player = NULL;
		MessageBlock mb(sizeof(int) * 30);
		for (int i = 0; i < reward_count && i < (int) result_vec.size(); i++)
		{
			player = result_vec[i].player();
			int real_win_chips = chips;
			if(player->win_chips_<=0)
			{
				real_win_chips = chips-player->cur_bet_chips_;
			}
			player->win_chips_ += chips;

			if(player->win_chips_<=player->cur_bet_chips_)
			{
				continue;
			}
			ProcResult &result = result_vec[i];
			mb.reset();
			mb << this->table_id() << player->role_id() << player->seat()
					<< UPDATE_WIN_CHIPS;
			mb << real_win_chips << result.type() << (int) result.result().size();
			for (CardVec::iterator iter = result.result().begin();
					iter != result.result().end(); iter++)
			{
				mb << (int) (*iter)->type_ << (int) (*iter)->number_;
			}
			this->broadcast_to_table(STC_BROADCAST_TABLE_INFO,&mb);
		}
	}
}

void Table::notify_operator(EnginePlayer *player, int time)
{
	MessageBlock mb(sizeof(int) * 30);
	mb.reset();
	mb << this->table_id() << player->role_id() << player->seat()
			<< UPDATE_CURR_OPERATOR << time;
	this->broadcast_to_table(STC_BROADCAST_TABLE_INFO, &mb);
}
